﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections.Specialized;

namespace ASPItalia.ModelVirtualCasting.WPF.Common
{
    public class ObservableCollectionEx<T> : ObservableCollection<T>
    {
        private bool _deferRefresh;

        public ObservableCollectionEx()
        {

        }

        public ObservableCollectionEx(IEnumerable<T> source)
            : base(source)
        {

        }

        protected override void OnPropertyChanged(System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (!_deferRefresh)
                base.OnPropertyChanged(e);
        }

        protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (!_deferRefresh)
                base.OnCollectionChanged(e);
        }

        public bool DeferRefresh
        {
            get { return _deferRefresh; }
            set
            {
                _deferRefresh = value;
            }
        }

        public IDisposable StartDeferRefresh(bool raiseEvents)
        {
            this.DeferRefresh = true;

            return new Disp(this, raiseEvents);
        }

        protected class Disp : IDisposable
        {
            private ObservableCollectionEx<T> parent;
            private readonly bool raiseEvents;

            public Disp(ObservableCollectionEx<T> parent, bool raiseEvents)
            {
                this.parent = parent;
                this.raiseEvents = raiseEvents;
            }

            #region IDisposable Members

            ///<summary>
            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
            ///</summary>
            ///<filterpriority>2</filterpriority>
            void IDisposable.Dispose()
            {
                this.parent.DeferRefresh = false;

                if (raiseEvents)
                {
                    parent.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
                    parent.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
                    parent.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                }
            }

            #endregion
        }

        public void AddRange(IEnumerable<T> source)
        {
            foreach (T item in source)
                this.Add(item);
        }
    }

}
